package com.aqa.ms.ref;

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.stream.IntStream;

/**
 * -Xmx:2048
 * 引用学习
 * 只有在回收之后才会被入队。
 */
public class RefKnow {


    public static void main(String[] args) throws InterruptedException {

        System.out.println("========================WeakRef===========================");
        ReferenceQueue<Obj> weakQueue = new ReferenceQueue<>();
        WeakReference<Obj> ref = new WeakReference<>(new Obj(), weakQueue);
        System.out.println("ref = " + ref + " ; ref.data = " + ref.get());

        System.gc();

        Thread printThread = new Thread(() -> {
            Reference<?> p;
            boolean flag = true;
            while (flag) {
                if (null != (p = weakQueue.poll())) {
                    System.out.println(Thread.currentThread().getName() + " >>>> pref = " + p + " pref.data = " + p.get());
                    flag = false;
                }
            }
        });
        printThread.start();
        System.out.println("ref.get() = " + ref.get());
        printThread.join();

        System.out.println("========================PhatRef===========================");
        ReferenceQueue<Obj> phatQueue = new ReferenceQueue<>();
        PhantomReference<Obj> phanRef = new PhantomReference<>(new Obj(), phatQueue);
        System.out.println("phanRef = " + phanRef + " ; phanRef.data = " + phanRef.get());

        System.gc();

        Thread printPhantThread = new Thread(() -> {
            Reference<?> p;
            boolean flag = true;
            while (flag) {
                if (null != (p = phatQueue.poll())) {
                    System.out.println(Thread.currentThread().getName() + " >>>> phanRef = " + p + " phanRef.data = " + p.get());
                    flag = false;
                }
            }
        });
        printPhantThread.start();
        System.out.println("phanRef.get() = " + phanRef.get());
        printPhantThread.join();


        System.out.println("========================SoftRef===========================");
        ReferenceQueue<Obj> softQueue = new ReferenceQueue<>();
        SoftReference<Obj> softRef = new SoftReference<>(new Obj(), softQueue);
        System.out.println("softRef = " + softRef + " ; softRef.data = " + softRef.get());

        System.gc();

        Thread print2 = new Thread(() -> {
            Reference<?> p;
            boolean flag = true;
            while (flag) {
                if (null != (p = softQueue.poll())) {
                    System.out.println(Thread.currentThread().getName() + " >>>> psoftRef = " + p + " psoftRef.data = " + p.get());
                    flag = false;
                }
            }
        });
        print2.start();

        ArrayList<Obj> liteObjs = new ArrayList<>();
        new Thread(() -> IntStream.range(0, 1000).forEach(i -> {
            liteObjs.add(new Obj());
            try {
                Thread.sleep(1000);
                System.out.println("softRef.get() = " + softRef.get());
                System.out.println("liteObjs.size() = " + liteObjs.size());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        })).start();
        System.out.println("liteObjs = " + liteObjs);
        print2.join();
    }


}

class Obj {
    byte[] rs = new byte[2048];
}

class LiteObj {
    byte[] rs = new byte[512];
}
